/*
 * Abstract accessing of data.
 *
 * General TODO:
 * - Ability to solve errors like missing permission, bad deletes or data corruption
 */
package org.dbdir.core;

import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import org.dbdir.core.datastore.db.SQLManager;
import org.dbdir.core.helper.*;

/**
 *
 * @author thotheolh
 */
public class AccessData {

    private SQLManager sql;

    public AccessData(String connPath, String username, String password) {
        sql = new SQLManager(connPath, username, password);
    }

    public AccessData(Connection conn) {
        sql = new SQLManager(conn);
    }

    public AccessData(SQLManager sql) {
        this.sql = sql;
    }

    public boolean doUserLogin(String username, String password) {
        User user = sql.getUserByName(username);
        if (user != null && user.getPassword().equals(password)) {
            return true;
        } else {
            return false;
        }
    }

    public boolean doUserLogin(String username, String password, String dbAlias) {
        User user = sql.getUserByName(username);
        ACL acl = sql.getACL(username, dbAlias);
        if ((acl != null) && (user.getPassword().equals(password))) {
            return true;
        } else {
            return false;
        }
    }

    public boolean doRegisterUser(String username, String password) {
        return sql.addUser(new User(username, password));
    }

    public boolean doUpdateUser(String username, String oldpass, String password) {
        User user = sql.getUserByName(username);
        if (user.getPassword().equals(oldpass)) {
            return sql.updateUser(username, password);
        } else {
            return false;
        }
    }

    public boolean doDeleteUser(String username) { //deletes user and the ACLs he is assigned
        ArrayList admList = sql.getAdminByUser(username);
        ArrayList aclList = sql.getDBListByUser(username);
        int isDelACLOk = 0;
        int isDelAdmOk = 0;
        Admin tempAdm;
        boolean ok1 = sql.deleteUser(username);
        if (!aclList.isEmpty()) {
            for (int i = 0; i < aclList.size(); i++) {
                boolean ok2 = sql.deleteACL(username, (String) aclList.get(i));
                if (ok2 == false) {
                    isDelACLOk++;
                }
            }
        }
        if (!admList.isEmpty()) {
            for (int i = 0; i < admList.size(); i++) {
                tempAdm = (Admin) admList.get(i);
                boolean ok3 = sql.deleteAllAdmin(tempAdm.getDbAlias());
                if (ok3 == false) {
                    isDelAdmOk++;
                }
            }
        }
        //System.out.println("ok1: "+ok1+", isDelACLOk: "+isDelACLOk+", isDelAdmOk: "+isDelAdmOk); //Diagnostic
        if (ok1 == true && isDelACLOk == 0 && isDelAdmOk == 0) {//TODO: Make sure to find all ACLs related to user and delete them
            return true;
        } else {
            return false;
        }

    }

    public boolean registerDatabase(String username, String dbAlias, String dbPath, String dbUsername, String dbPassword) {
        boolean ok1 = sql.addDatabaseInfo(new Database(dbAlias, dbPath, dbUsername, dbPassword, new Timestamp(new Date().getTime())));
        boolean ok2 = sql.addACL(new ACL(username, dbAlias, true, true, true, true, true, true, true));
        boolean ok3 = sql.addAdmin(new Admin(username, dbAlias));
        if (ok1 == true && ok2 == true && ok3 == true) {
            return true;
        } else {
            return false;
        }
    }

    public Database getDatabaseInfo(String username, String dbAlias) {
        ACL access = new ACL();
        access = sql.getACL(username, dbAlias);
        Database db = new Database();
        db = sql.getDatabaseInfoByName(dbAlias);
        if (access.isShowDbPath() == false) {
            db.setDbPath(null);
        }
        if (access.isShowDbUsername() == false) {
            db.setDbUsername(null);
        }
        if (access.isShowDbPassword() == false) {
            db.setDbPassword(null);
        }
        if (access.isShowDateTimeReg() == false) {
            db.setDatetimeResgistered(null);
        }
        return db;
    }

    public boolean updateDatabaseInfo(String username, Database setdb) {
        ACL access = new ACL();
        access = sql.getACL(username, setdb.getDbAlias());
        Database realdb = new Database();
        realdb = sql.getDatabaseInfoByName(setdb.getDbAlias());
        if (access.isEditDbPath() == true) {
            realdb.setDbPath(setdb.getDbPath());
        }
        if (access.isEditDbUsername() == true) {
            realdb.setDbUsername(setdb.getDbUsername());
        }
        if (access.isEditDbPassword() == true) {
            realdb.setDbPassword(setdb.getDbPassword());
        }
        return sql.updateDatabaseInfo(realdb);
    }

    public boolean deleteDatabase(String username, String dbAlias) {
        //TODO:Check if the username is an admin and iterate to delete all ACLs related to the database
        //TODO: Create an sql statement to gather a list of usernames for targeted dbAlias
        int err = 0;
        boolean ok;
        if (isDBAdmin(username, dbAlias)) {
            if (sql.deleteDatabaseInfo(dbAlias)) {
                ArrayList userList = sql.getUserListByDB(dbAlias);
                for (int i = 0; i < userList.size(); i++) {
                    ok = sql.deleteACL(userList.get(i).toString(), dbAlias);
                    if (ok == false) {
                        err++;
                    }
                }
                if (sql.deleteAllAdmin(dbAlias)) {
                } else {
                    err++;
                }
                if (err == 0) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public boolean changeAccessPermission(String changerName, String dbAlias, ACL access) {
        if (sql.checkAdminByUserDB(changerName, dbAlias)) {
            return sql.updateACL(access);
        } else {
            return false;
        }
    }

    public boolean changeAdmin(String oldAdmin, String newAdmin, String dbAlias) {
        if (sql.checkAdminByUserDB(oldAdmin, dbAlias)) {
            return sql.updateAdmin(oldAdmin, newAdmin, dbAlias);
        } else {
            return false;
        }
    }

    public boolean joinDatabase(String username, String dbname) {
        ACL acl = new ACL(username, dbname, true, true, true, true, false, false, false);
        return sql.addACL(acl);
    }

    public boolean rmUserFromDatabase(String username, String dbname) {
        return sql.deleteACL(username, dbname);
    }

    public boolean isUserExistDB(String username, String dbname) {
        if (sql.getACL(username, dbname) == null) {
            return false;
        } else {
            return true;
        }
    }

    public boolean isUserExist(String username) {
        if (sql.getUserByName(username) != null) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isDBAdmin(String username, String dbname) {
        if (sql.checkAdminByUserDB(username, dbname)) {
            return true;
        } else {
            return false;
        }
    }

    public ArrayList getUserDBList(String username) {
        ArrayList dbList = sql.getUserDBList(username);
        return dbList;
    }

    public SQLManager getSQLManager() {
        return sql;
    }

    public ACL getPermission(String val_Username, String val_Alias) {
        return sql.getACL(val_Username, val_Alias);
    }

//    ArrayList getAvDBList(String username) {  //version 1 codes
//        ArrayList dbList = sql.listDBAlias();
//        ArrayList usrDBLs = sql.getUserDBList(username);
//        String checkingDB;
//        String checkingUsr;
//        System.out.println(dbList.toString());
//        System.out.println(usrDBLs.toString());
//
//        for (int i = 0; i < dbList.size(); i++) {
//            checkingDB = dbList.get(i).toString();
////            System.out.println("Checking dbList " + checkingDB);
//
//            for (int j = 0; j < usrDBLs.size(); j++) {
//                checkingUsr = usrDBLs.get(j).toString();
////                System.out.println("Checking usrDBLs " + checkingUsr);
//                if (checkingDB.equals(checkingUsr)) {
//                    //dbList.remove(i);
//                    dbList.remove(checkingDB);
//                //System.out.println(dbList.toString());
//                }
//            }
//        }
//        System.out.println(dbList.toString());
//        return dbList;
//    }
    ArrayList getAvDBList(String username) { //version 2 codes
        ArrayList dbList = sql.listDBAlias();
        ArrayList usrDBLs = sql.getUserDBList(username);
        String checkingDB;
        String checkingUsr;
//        System.out.println(dbList.toString());
//        System.out.println(usrDBLs.toString());

        for (int j = 0; j < usrDBLs.size(); j++) {
            checkingUsr = usrDBLs.get(j).toString();

//            System.out.println("Checking dbList " + checkingDB);

            for (int i = 0; i < dbList.size(); i++) {
                checkingDB = dbList.get(i).toString();
//                System.out.println("Checking usrDBLs " + checkingUsr);
                if (checkingDB.equals(checkingUsr)) {
                    //dbList.remove(i);
                    dbList.remove(checkingDB);
                //System.out.println(dbList.toString());
                }
            }
        }
//        System.out.println(dbList.toString());
        return dbList;
    }

    ArrayList getDBUserList(String dbname, String rqname) {
        ArrayList usrList = sql.getUserListByDB(dbname);
        for (int i = 0; i < usrList.size(); i++) {
            if (usrList.get(i).equals(rqname)) {
                usrList.remove(i);
            }
        }
        return usrList;
    }
}
